Worldbank GDP per capita data
Data source from worldbank GDP per capita in current USD value. We using per capita value to normalized against each country population for comparison between countries. The data is then unstack and merge with the data set setup earlier with Barro-Lee’s education statistics.
PCA plot
We added in GDP data and perform PCA again. PC2 and PC3 shows hyper-plane that is in 3-D with a slight slope when mapped to 2 dimension. Drawing a 3-D plot including PC 1, 2 and 3 shows a better view on these hyper-planes.
pca.data<-as.matrix(new.ext %>% select( Elevation, Number.of.speakers.log, GDP.per.capita.log, `Female.75+.completed.secondary`))
rownames(pca.data)<-as.character(new.ext$Degree.of.endangerment)
pca.barrolee <- princomp(apply(pca.data, 2, rank))
lambda <- (pca.barrolee$sdev)^2
propvar <- round(lambda / sum(lambda) * 100, 0)
3D PCA plot on PC1, PC2 and PC3
The 3-D scatter plot shows the weight of each generation vulnerability clustering. The green points with vulnerability on generation 1 (grandparents) and generation 2 (parents) are clustered together with some cross over to blue region that covers generation 3 (children). The red (extinct) are clearly on its plane (mainly due to number of speakers for extinction is 0, which is clearly separable to the others)
color<-c(rep(rgb(0,0,1, 0.3), 2), rep(rgb(0,1,0, 0.3), 2), rgb(1,0,0, 0.3))
camera<-list(eye=list(x = -1.8, y = 0.8, z = 0.2))
scene = list(
xaxis=list(title="PCA1"), yaxis=list(title="PCA2"),
zaxis=list(title="PCA3"),
camera = camera)
plot_ly(x = pca.barrolee$scores[,1],
y = pca.barrolee$scores[,2],
z = pca.barrolee$scores[,3],
color = factor(rownames(pca.barrolee$scores),
levels=c("Vulnerable",
"Definitely endangered",
"Severely endangered",
"Critically endangered", "Extinct")), colors = color) %>%
add_markers(opacity=0.3, marker=list(size=rep(7, nrow(pca.data)))) %>% layout(scene=scene)
PCA plot on PC2 and PC3
Slope on projection to PC2 and PC3 plane suggest a 3 D view.
plotPCA(2,3, pca.barrolee, color)

PCA plot on PC1 and PC3

PCA plot on PC1 and PC2
plotPCA(1,2, pca.barrolee, color)

PCA Biplot
The biplot shows Elevation and Number of speakers are closely related with degree between the 2 vectors to be small, moving towards same direction and magnitude. It is also orthogonal (independence) in respect to the other 2 variables, GDP per capita and Percentage of female 75+ population that completed secondary school.
biplot(pca.barrolee, xlabs = rep('', nrow(pca.data)), cex=0.6)

pca.barrolee$loadings
Loadings:
Comp.1 Comp.2 Comp.3 Comp.4
Elevation -0.307 -0.659 0.685
Number.of.speakers.log -0.332 -0.599 -0.728
GDP.per.capita.log 0.639 -0.281 -0.715
Female.75+.completed.secondary 0.621 -0.357 0.697
Comp.1 Comp.2 Comp.3 Comp.4
SS loadings 1.00 1.00 1.00 1.00
Proportion Var 0.25 0.25 0.25 0.25
Cumulative Var 0.25 0.50 0.75 1.00
Draftman’s Plot
The Draftman’s plot shows Number of speakers are clearly having direct relation with the vulnerability, which is expected as lower numbers of speakers contribute directly on the spread of the language. However, the plot against Number of speakers versus Percentage of 75+ female population that completed secondary school shows a break in blue points (generation 3 or young children). Supporting our argument that generation 1 (grandparents) population with secondary education are showing evidence of shift to national language as main communication with their children. Taking a breaking point of percent 75+ female population that completed secondary school at 30% yields a 23% of languages with vulnerability on generation 3 (blue points) compared with 53% of total languages that is with lower education penetration on generation 1 (grandparents).
color<-c(rep(rgb(0,0,1, 0.2), 2), rep(rgb(0,1,0, 0.2), 2), rgb(1,0,0, 0.2))
pairs(pca.data, pch=21, col=rgb(0,0,0,0),
bg=color[unclass(factor(rownames(pca.data),levels=c("Vulnerable", "Definitely endangered", "Severely endangered", "Critically endangered", "Extinct")))])

Correlation on GDP vs Education
Even though is speculated that education level is highly correlated with GDP (economic growth), drawing a comparison between the 2 in log scale for education penetration level on generation 1 only explain 60% of economic growth based on GDP per capita. We argue that economic growth may be a driving force for generation 1 with higher education penetration to often use mainstream language for communication at home. This indirectly causing a breakage in cultural language transfer between generation.
color<-c(rep(rgb(0,0,1, 0.2), 2), rep(rgb(0,1,0, 0.2), 2), rgb(1,0,0, 0.2))
new.ext<- new.ext %>% mutate(`Female.75+.completed.secondary.log`=
ifelse(`Female.75+.completed.secondary`==0,
log(1), log(`Female.75+.completed.secondary`)))
plot(GDP.per.capita.log~`Female.75+.completed.secondary.log`, data=new.ext, pch=21, col=rgb(0,0,0,0),
bg=color[unclass(factor(new.ext$Degree.of.endangerment,levels=c("Vulnerable", "Definitely endangered", "Severely endangered", "Critically endangered", "Extinct")))])
lm.fit<-lm(GDP.per.capita.log~`Female.75+.completed.secondary.log`, data=new.ext)
abline(lm.fit)

summary(lm.fit)
Call:
lm(formula = GDP.per.capita.log ~ `Female.75+.completed.secondary.log`,
data = new.ext)
Residuals:
Min 1Q Median 3Q Max
-4.2934 -0.6686 0.1462 0.6894 3.4807
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 7.275826 0.010607 685.9 <2e-16 ***
`Female.75+.completed.secondary.log` 0.656306 0.004962 132.3 <2e-16 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 0.975 on 11217 degrees of freedom
Multiple R-squared: 0.6093, Adjusted R-squared: 0.6093
F-statistic: 1.749e+04 on 1 and 11217 DF, p-value: < 2.2e-16
Appendix
require(reshape2)
require(dplyr)
filterByYearUnstack<-function(edstats.df, fromYear=1976, toYear=2016) {
getYear<-function(yr) {
as.numeric(gsub("X([0-9]{4})", "\\1", yr))
}
edstats.years<-data.frame()
for(n in names(edstats)) {
if (grepl("X[0-9]{4}", n) && getYear(n) >=fromYear && getYear(n) <= toYear)
edstats.years<-rbind(edstats.years, edstats.df %>%
dcast(Country.Code~Indicator.Name, value.var= n) %>%
mutate(year=gsub("X([0-9]{4})", "\\1", n)))
}
edstats.years
}
ext.lang.elevation<-readRDS(file="collected_data/ext.lang.elevation.country.normalized.RDS")
edstats.barrolee.l<-readRDS("./collected_data/edstats.barrolee.RDS")
gdp.capita<-read.csv("../input/API_NY-GDPperCapita/API_NY.GDP.PCAP.CD_DS2_en_csv_v2.csv", skip = 4)
doe.levels<-levels(factor(ext.lang.elevation$Degree.of.endangerment,
levels=c("Vulnerable", "Definitely endangered",
"Severely endangered", "Critically endangered", "Extinct")))
gdp.capita<-filterByYearUnstack(gdp.capita, 1990, 2010)
ed.gdp<-merge(edstats.barrolee.l, gdp.capita, by=c("Country.Code", "year"), all.x=T) %>%
filter(!is.na(`GDP per capita (current US$)`))
ctr.diff<-setdiff(ext.lang.elevation$Country.codes.alpha.3.coord, edstats.barrolee.l$Country.Code)
new.ext<-ext.lang.elevation %>% filter(!(Country.codes.alpha.3.coord %in% ctr.diff)) %>%
filter(!is.na(Number.of.speakers)) %>%
select(ID, Degree.of.endangerment, Name.in.English, Number.of.speakers, elevation, Country.codes.alpha.3.coord )
new.ext<-new.ext %>% mutate(Number.of.speakers.log = ifelse(Number.of.speakers==0, log(1), log(Number.of.speakers)))
## Merge for all years
new.ext<-merge(new.ext, ed.gdp, by.x="Country.codes.alpha.3.coord",
by.y = "Country.Code", all.x=T) %>% select ( - matches("year") )
new.ext<-new.ext %>% mutate(GDP.per.capita.log = log(`GDP per capita (current US$)`))
new.ext<-new.ext %>% mutate( `Female.75+.completed.secondary.log` = log(`Barro-Lee: Percentage of female population age 75+ with secondary schooling. Completed Secondary`))
new.ext<-new.ext %>% mutate( `Female.75+.completed.secondary` = `Barro-Lee: Percentage of female population age 75+ with secondary schooling. Completed Secondary`)
new.ext<-new.ext %>% select(-starts_with("Barro-Lee:"))
new.ext<-new.ext %>% plyr::rename(c("Country.codes.alpha.3.coord" = "Country.Code", "elevation" = "Elevation"))
plotPCA<-function(f, s, pca.barrolee, color, titl=TRUE) {
plot(pca.barrolee$scores[,f], pca.barrolee$scores[,s], pch=21,
xlab=paste(c("PC",f,"(",propvar[f],"%)"), collapse=""),
ylab=paste(c("PC",s,"(",propvar[s],"%)"), collapse=""),
col=rgb(0,0,0,0), bg=color[unclass(factor(new.ext$Degree.of.endangerment,
levels=c("Vulnerable", "Definitely endangered", "Severely endangered",
"Critically endangered", "Extinct")))])
legend("bottomright", doe.levels, col=color,
cex=0.7,
pch=rep(19, length(doe.levels)))
if (titl)
title(paste("PCA PC", f," and PC", s, sep=""))
}
LS0tCnRpdGxlOiAiTWVyZ2luZyBXb3JsZCBFbmRhbmdlcmVkIExhbmd1YWdlIGRhdGEgd2l0aCBHRFAgcGVyIENhcGl0YSIKb3V0cHV0OiAKICBodG1sX25vdGVib29rOiBkZWZhdWx0CiAgaHRtbF9kb2N1bWVudDogZGVmYXVsdAotLS0KYGBge3IgcmVmLmxhYmVsPWMoImluaXQiLCAidW5zdGFjayIsICJwbG90UENBIiksIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CnJlcXVpcmUocGxvdGx5KQpgYGAKCiMjIyBXb3JsZGJhbmsgR0RQIHBlciBjYXBpdGEgZGF0YQoKRGF0YSBzb3VyY2UgZnJvbSB3b3JsZGJhbmsgW0dEUCBwZXIgY2FwaXRhIGluIGN1cnJlbnQgVVNEIHZhbHVlXShodHRwOi8vZGF0YS53b3JsZGJhbmsub3JnL2luZGljYXRvci9OWS5HRFAuUENBUC5DRCkuIFdlIHVzaW5nIHBlciBjYXBpdGEgdmFsdWUgdG8gbm9ybWFsaXplZCBhZ2FpbnN0IGVhY2ggY291bnRyeSBwb3B1bGF0aW9uIGZvciBjb21wYXJpc29uIGJldHdlZW4gY291bnRyaWVzLiBUaGUgZGF0YSBpcyB0aGVuIHVuc3RhY2sgYW5kIG1lcmdlIHdpdGggdGhlIGRhdGEgc2V0IHNldHVwIGVhcmxpZXIgd2l0aCBCYXJyby1MZWUncyBlZHVjYXRpb24gc3RhdGlzdGljcy4KCiMjIyBQQ0EgcGxvdCB7LnRhYnNldH0KCldlIGFkZGVkIGluIEdEUCBkYXRhIGFuZCBwZXJmb3JtIFBDQSBhZ2Fpbi4gUEMyIGFuZCBQQzMgc2hvd3MgaHlwZXItcGxhbmUgdGhhdCBpcyBpbiAzLUQgd2l0aCBhIHNsaWdodCBzbG9wZSB3aGVuIG1hcHBlZCB0byAyIGRpbWVuc2lvbi4gRHJhd2luZyBhIDMtRCBwbG90IGluY2x1ZGluZyBQQyAxLCAyIGFuZCAzIHNob3dzIGEgYmV0dGVyIHZpZXcgb24gdGhlc2UgaHlwZXItcGxhbmVzLgoKYGBge3J9CnBjYS5kYXRhPC1hcy5tYXRyaXgobmV3LmV4dCAlPiUgc2VsZWN0KCBFbGV2YXRpb24sIE51bWJlci5vZi5zcGVha2Vycy5sb2csIEdEUC5wZXIuY2FwaXRhLmxvZywgYEZlbWFsZS43NSsuY29tcGxldGVkLnNlY29uZGFyeWApKQoKcm93bmFtZXMocGNhLmRhdGEpPC1hcy5jaGFyYWN0ZXIobmV3LmV4dCREZWdyZWUub2YuZW5kYW5nZXJtZW50KQpwY2EuYmFycm9sZWUgPC0gcHJpbmNvbXAoYXBwbHkocGNhLmRhdGEsIDIsIHJhbmspKQpsYW1iZGEgPC0gKHBjYS5iYXJyb2xlZSRzZGV2KV4yIApwcm9wdmFyIDwtIHJvdW5kKGxhbWJkYSAvIHN1bShsYW1iZGEpICogMTAwLCAwKQpgYGAKCiMjIyMgM0QgUENBIHBsb3Qgb24gUEMxLCBQQzIgYW5kIFBDMwoKVGhlIDMtRCBzY2F0dGVyIHBsb3Qgc2hvd3MgdGhlIHdlaWdodCBvZiBlYWNoIGdlbmVyYXRpb24gdnVsbmVyYWJpbGl0eSBjbHVzdGVyaW5nLiBUaGUgZ3JlZW4gcG9pbnRzIHdpdGggdnVsbmVyYWJpbGl0eSBvbiBnZW5lcmF0aW9uIDEgKGdyYW5kcGFyZW50cykgYW5kIGdlbmVyYXRpb24gMiAocGFyZW50cykgYXJlIGNsdXN0ZXJlZCB0b2dldGhlciB3aXRoIHNvbWUgY3Jvc3Mgb3ZlciB0byBibHVlIHJlZ2lvbiB0aGF0IGNvdmVycyBnZW5lcmF0aW9uIDMgKGNoaWxkcmVuKS4gVGhlIHJlZCAoZXh0aW5jdCkgYXJlIGNsZWFybHkgb24gaXRzIHBsYW5lIChtYWlubHkgZHVlIHRvIG51bWJlciBvZiBzcGVha2VycyBmb3IgZXh0aW5jdGlvbiBpcyAwLCB3aGljaCBpcyBjbGVhcmx5IHNlcGFyYWJsZSB0byB0aGUgb3RoZXJzKQoKYGBge3J9CmNvbG9yPC1jKHJlcChyZ2IoMCwwLDEsIDAuMyksIDIpLCByZXAocmdiKDAsMSwwLCAwLjMpLCAyKSwgcmdiKDEsMCwwLCAwLjMpKQpjYW1lcmE8LWxpc3QoZXllPWxpc3QoeCA9IC0xLjgsIHkgPSAwLjgsIHogPSAwLjIpKQpzY2VuZSA9IGxpc3QoCiAgeGF4aXM9bGlzdCh0aXRsZT0iUENBMSIpLCB5YXhpcz1saXN0KHRpdGxlPSJQQ0EyIiksCiAgemF4aXM9bGlzdCh0aXRsZT0iUENBMyIpLAogIGNhbWVyYSA9IGNhbWVyYSkKcGxvdF9seSh4ID0gcGNhLmJhcnJvbGVlJHNjb3Jlc1ssMV0sIAogICAgICAgICAgICAgeSA9IHBjYS5iYXJyb2xlZSRzY29yZXNbLDJdLCAKICAgICAgICAgICAgIHogPSBwY2EuYmFycm9sZWUkc2NvcmVzWywzXSwgCiAgICAgICAgICAgICBjb2xvciA9IGZhY3Rvcihyb3duYW1lcyhwY2EuYmFycm9sZWUkc2NvcmVzKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzPWMoIlZ1bG5lcmFibGUiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkRlZmluaXRlbHkgZW5kYW5nZXJlZCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiU2V2ZXJlbHkgZW5kYW5nZXJlZCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ3JpdGljYWxseSBlbmRhbmdlcmVkIiwgIkV4dGluY3QiKSksIGNvbG9ycyA9IGNvbG9yKSAlPiUKICBhZGRfbWFya2VycyhvcGFjaXR5PTAuMywgbWFya2VyPWxpc3Qoc2l6ZT1yZXAoNywgbnJvdyhwY2EuZGF0YSkpKSkgJT4lIGxheW91dChzY2VuZT1zY2VuZSkKYGBgCgoKIyMjIyBQQ0EgcGxvdCBvbiBQQzIgYW5kIFBDMwoKU2xvcGUgb24gcHJvamVjdGlvbiB0byBQQzIgYW5kIFBDMyBwbGFuZSBzdWdnZXN0IGEgMyBEIHZpZXcuCgpgYGB7cn0KcGxvdFBDQSgyLDMsIHBjYS5iYXJyb2xlZSwgY29sb3IpCmBgYAoKCiMjIyMgUENBIHBsb3Qgb24gUEMxIGFuZCBQQzMKCmBgYHtyfQpwbG90UENBKDEsMywgcGNhLmJhcnJvbGVlLCBjb2xvcikKYGBgCgojIyMjIFBDQSBwbG90IG9uIFBDMSBhbmQgUEMyCgpgYGB7cn0KcGxvdFBDQSgxLDIsIHBjYS5iYXJyb2xlZSwgY29sb3IpCmBgYAoKCiMjIyBQQ0EgQmlwbG90CgpUaGUgYmlwbG90IHNob3dzICoqRWxldmF0aW9uKiogYW5kICoqTnVtYmVyIG9mIHNwZWFrZXJzKiogYXJlIGNsb3NlbHkgcmVsYXRlZCB3aXRoIGRlZ3JlZSBiZXR3ZWVuIHRoZSAyIHZlY3RvcnMgdG8gYmUgc21hbGwsIG1vdmluZyB0b3dhcmRzIHNhbWUgZGlyZWN0aW9uIGFuZCBtYWduaXR1ZGUuIEl0IGlzIGFsc28gb3J0aG9nb25hbCAoaW5kZXBlbmRlbmNlKSBpbiByZXNwZWN0IHRvIHRoZSBvdGhlciAyIHZhcmlhYmxlcywgKipHRFAgcGVyIGNhcGl0YSoqIGFuZCAqKlBlcmNlbnRhZ2Ugb2YgZmVtYWxlIDc1KyBwb3B1bGF0aW9uIHRoYXQgY29tcGxldGVkIHNlY29uZGFyeSBzY2hvb2wqKi4KCmBgYHtyfQpiaXBsb3QocGNhLmJhcnJvbGVlLCB4bGFicyA9IHJlcCgnJywgbnJvdyhwY2EuZGF0YSkpLCBjZXg9MC42KQpwY2EuYmFycm9sZWUkbG9hZGluZ3MKYGBgCgojIyMgRHJhZnRtYW4ncyBQbG90CgpUaGUgRHJhZnRtYW4ncyBwbG90IHNob3dzICoqTnVtYmVyIG9mIHNwZWFrZXJzKiogYXJlIGNsZWFybHkgaGF2aW5nIGRpcmVjdCByZWxhdGlvbiB3aXRoIHRoZSB2dWxuZXJhYmlsaXR5LCB3aGljaCBpcyBleHBlY3RlZCBhcyBsb3dlciBudW1iZXJzIG9mIHNwZWFrZXJzIGNvbnRyaWJ1dGUgZGlyZWN0bHkgb24gdGhlIHNwcmVhZCBvZiB0aGUgbGFuZ3VhZ2UuIEhvd2V2ZXIsIHRoZSBwbG90IGFnYWluc3QgKipOdW1iZXIgb2Ygc3BlYWtlcnMqKiB2ZXJzdXMgKipQZXJjZW50YWdlIG9mIDc1KyBmZW1hbGUgcG9wdWxhdGlvbiB0aGF0IGNvbXBsZXRlZCBzZWNvbmRhcnkgc2Nob29sKiogc2hvd3MgYSBicmVhayBpbiBibHVlIHBvaW50cyAoZ2VuZXJhdGlvbiAzIG9yIHlvdW5nIGNoaWxkcmVuKS4gU3VwcG9ydGluZyBvdXIgYXJndW1lbnQgdGhhdCBnZW5lcmF0aW9uIDEgKGdyYW5kcGFyZW50cykgcG9wdWxhdGlvbiB3aXRoIHNlY29uZGFyeSBlZHVjYXRpb24gYXJlIHNob3dpbmcgZXZpZGVuY2Ugb2Ygc2hpZnQgdG8gbmF0aW9uYWwgbGFuZ3VhZ2UgYXMgbWFpbiBjb21tdW5pY2F0aW9uIHdpdGggdGhlaXIgY2hpbGRyZW4uIFRha2luZyBhIGJyZWFraW5nIHBvaW50IG9mIHBlcmNlbnQgNzUrIGZlbWFsZSBwb3B1bGF0aW9uIHRoYXQgY29tcGxldGVkIHNlY29uZGFyeSBzY2hvb2wgYXQgMzAlIHlpZWxkcyBhIDIzJSBvZiBsYW5ndWFnZXMgd2l0aCB2dWxuZXJhYmlsaXR5IG9uIGdlbmVyYXRpb24gMyAoYmx1ZSBwb2ludHMpIGNvbXBhcmVkIHdpdGggNTMlIG9mIHRvdGFsIGxhbmd1YWdlcyB0aGF0IGlzIHdpdGggbG93ZXIgZWR1Y2F0aW9uIHBlbmV0cmF0aW9uIG9uIGdlbmVyYXRpb24gMSAoZ3JhbmRwYXJlbnRzKS4gCgpgYGB7cn0KY29sb3I8LWMocmVwKHJnYigwLDAsMSwgMC4yKSwgMiksIHJlcChyZ2IoMCwxLDAsIDAuMiksIDIpLCByZ2IoMSwwLDAsIDAuMikpCnBhaXJzKHBjYS5kYXRhLCBwY2g9MjEsIGNvbD1yZ2IoMCwwLDAsMCksCiAgICAgIGJnPWNvbG9yW3VuY2xhc3MoZmFjdG9yKHJvd25hbWVzKHBjYS5kYXRhKSxsZXZlbHM9YygiVnVsbmVyYWJsZSIsICJEZWZpbml0ZWx5IGVuZGFuZ2VyZWQiLCAiU2V2ZXJlbHkgZW5kYW5nZXJlZCIsICJDcml0aWNhbGx5IGVuZGFuZ2VyZWQiLCAiRXh0aW5jdCIpKSldKQoKYGBgCgojIyMgQ29ycmVsYXRpb24gb24gR0RQIHZzIEVkdWNhdGlvbgoKRXZlbiB0aG91Z2ggaXMgc3BlY3VsYXRlZCB0aGF0IGVkdWNhdGlvbiBsZXZlbCBpcyBoaWdobHkgY29ycmVsYXRlZCB3aXRoIEdEUCAoZWNvbm9taWMgZ3Jvd3RoKSwgZHJhd2luZyBhIGNvbXBhcmlzb24gYmV0d2VlbiB0aGUgMiBpbiBsb2cgc2NhbGUgZm9yIGVkdWNhdGlvbiBwZW5ldHJhdGlvbiBsZXZlbCBvbiBnZW5lcmF0aW9uIDEgb25seSBleHBsYWluIDYwJSBvZiBlY29ub21pYyBncm93dGggYmFzZWQgb24gR0RQIHBlciBjYXBpdGEuIFdlIGFyZ3VlIHRoYXQgZWNvbm9taWMgZ3Jvd3RoIG1heSBiZSBhIGRyaXZpbmcgZm9yY2UgZm9yIGdlbmVyYXRpb24gMSB3aXRoIGhpZ2hlciBlZHVjYXRpb24gcGVuZXRyYXRpb24gdG8gb2Z0ZW4gdXNlIG1haW5zdHJlYW0gbGFuZ3VhZ2UgZm9yIGNvbW11bmljYXRpb24gYXQgaG9tZS4gVGhpcyBpbmRpcmVjdGx5IGNhdXNpbmcgYSBicmVha2FnZSBpbiBjdWx0dXJhbCBsYW5ndWFnZSB0cmFuc2ZlciBiZXR3ZWVuIGdlbmVyYXRpb24uCgpgYGB7cn0KY29sb3I8LWMocmVwKHJnYigwLDAsMSwgMC4yKSwgMiksIHJlcChyZ2IoMCwxLDAsIDAuMiksIDIpLCByZ2IoMSwwLDAsIDAuMikpCgpuZXcuZXh0PC0gbmV3LmV4dCAlPiUgbXV0YXRlKGBGZW1hbGUuNzUrLmNvbXBsZXRlZC5zZWNvbmRhcnkubG9nYD0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShgRmVtYWxlLjc1Ky5jb21wbGV0ZWQuc2Vjb25kYXJ5YD09MCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbG9nKDEpLCBsb2coYEZlbWFsZS43NSsuY29tcGxldGVkLnNlY29uZGFyeWApKSkKcGxvdChHRFAucGVyLmNhcGl0YS5sb2d+YEZlbWFsZS43NSsuY29tcGxldGVkLnNlY29uZGFyeS5sb2dgLCAgZGF0YT1uZXcuZXh0LCBwY2g9MjEsIGNvbD1yZ2IoMCwwLDAsMCksCiAgICAgIGJnPWNvbG9yW3VuY2xhc3MoZmFjdG9yKG5ldy5leHQkRGVncmVlLm9mLmVuZGFuZ2VybWVudCxsZXZlbHM9YygiVnVsbmVyYWJsZSIsICJEZWZpbml0ZWx5IGVuZGFuZ2VyZWQiLCAiU2V2ZXJlbHkgZW5kYW5nZXJlZCIsICJDcml0aWNhbGx5IGVuZGFuZ2VyZWQiLCAiRXh0aW5jdCIpKSldKQpsbS5maXQ8LWxtKEdEUC5wZXIuY2FwaXRhLmxvZ35gRmVtYWxlLjc1Ky5jb21wbGV0ZWQuc2Vjb25kYXJ5LmxvZ2AsICBkYXRhPW5ldy5leHQpCmFibGluZShsbS5maXQpCmBgYAoKCmBgYHtyfQpzdW1tYXJ5KGxtLmZpdCkKYGBgCgoKIyMjIEFwcGVuZGl4CgpgYGB7ciB1bnN0YWNrfQpyZXF1aXJlKHJlc2hhcGUyKQpyZXF1aXJlKGRwbHlyKQpmaWx0ZXJCeVllYXJVbnN0YWNrPC1mdW5jdGlvbihlZHN0YXRzLmRmLCBmcm9tWWVhcj0xOTc2LCB0b1llYXI9MjAxNikgewogIGdldFllYXI8LWZ1bmN0aW9uKHlyKSB7CiAgICBhcy5udW1lcmljKGdzdWIoIlgoWzAtOV17NH0pIiwgIlxcMSIsIHlyKSkKICB9CiAgZWRzdGF0cy55ZWFyczwtZGF0YS5mcmFtZSgpCiAgZm9yKG4gaW4gbmFtZXMoZWRzdGF0cykpIHsKICAgIGlmIChncmVwbCgiWFswLTldezR9IiwgbikgJiYgZ2V0WWVhcihuKSA+PWZyb21ZZWFyICYmIGdldFllYXIobikgPD0gdG9ZZWFyKQogICAgICBlZHN0YXRzLnllYXJzPC1yYmluZChlZHN0YXRzLnllYXJzLCBlZHN0YXRzLmRmICU+JSAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkY2FzdChDb3VudHJ5LkNvZGV+SW5kaWNhdG9yLk5hbWUsIHZhbHVlLnZhcj0gbikgJT4lIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIG11dGF0ZSh5ZWFyPWdzdWIoIlgoWzAtOV17NH0pIiwgIlxcMSIsIG4pKSkKICB9CiAgZWRzdGF0cy55ZWFycwp9CmBgYAoKCmBgYHtyIGluaXQsIGNhY2hlPVRSVUV9CmV4dC5sYW5nLmVsZXZhdGlvbjwtcmVhZFJEUyhmaWxlPSJjb2xsZWN0ZWRfZGF0YS9leHQubGFuZy5lbGV2YXRpb24uY291bnRyeS5ub3JtYWxpemVkLlJEUyIpCmVkc3RhdHMuYmFycm9sZWUubDwtcmVhZFJEUygiLi9jb2xsZWN0ZWRfZGF0YS9lZHN0YXRzLmJhcnJvbGVlLlJEUyIpCmdkcC5jYXBpdGE8LXJlYWQuY3N2KCIuLi9pbnB1dC9BUElfTlktR0RQcGVyQ2FwaXRhL0FQSV9OWS5HRFAuUENBUC5DRF9EUzJfZW5fY3N2X3YyLmNzdiIsIHNraXAgPSA0KQoKZG9lLmxldmVsczwtbGV2ZWxzKGZhY3RvcihleHQubGFuZy5lbGV2YXRpb24kRGVncmVlLm9mLmVuZGFuZ2VybWVudCwKICAgICAgICAgICAgICAgICAgIGxldmVscz1jKCJWdWxuZXJhYmxlIiwgIkRlZmluaXRlbHkgZW5kYW5nZXJlZCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIlNldmVyZWx5IGVuZGFuZ2VyZWQiLCAiQ3JpdGljYWxseSBlbmRhbmdlcmVkIiwgIkV4dGluY3QiKSkpCmdkcC5jYXBpdGE8LWZpbHRlckJ5WWVhclVuc3RhY2soZ2RwLmNhcGl0YSwgMTk5MCwgMjAxMCkKCmVkLmdkcDwtbWVyZ2UoZWRzdGF0cy5iYXJyb2xlZS5sLCBnZHAuY2FwaXRhLCBieT1jKCJDb3VudHJ5LkNvZGUiLCAieWVhciIpLCBhbGwueD1UKSAlPiUgCiAgZmlsdGVyKCFpcy5uYShgR0RQIHBlciBjYXBpdGEgKGN1cnJlbnQgVVMkKWApKQpjdHIuZGlmZjwtc2V0ZGlmZihleHQubGFuZy5lbGV2YXRpb24kQ291bnRyeS5jb2Rlcy5hbHBoYS4zLmNvb3JkLCBlZHN0YXRzLmJhcnJvbGVlLmwkQ291bnRyeS5Db2RlKQoKbmV3LmV4dDwtZXh0LmxhbmcuZWxldmF0aW9uICU+JSBmaWx0ZXIoIShDb3VudHJ5LmNvZGVzLmFscGhhLjMuY29vcmQgJWluJSBjdHIuZGlmZikpICU+JQogIGZpbHRlcighaXMubmEoTnVtYmVyLm9mLnNwZWFrZXJzKSkgJT4lCiAgc2VsZWN0KElELCBEZWdyZWUub2YuZW5kYW5nZXJtZW50LCBOYW1lLmluLkVuZ2xpc2gsIE51bWJlci5vZi5zcGVha2VycywgZWxldmF0aW9uLCBDb3VudHJ5LmNvZGVzLmFscGhhLjMuY29vcmQgKQpuZXcuZXh0PC1uZXcuZXh0ICU+JSBtdXRhdGUoTnVtYmVyLm9mLnNwZWFrZXJzLmxvZyA9IGlmZWxzZShOdW1iZXIub2Yuc3BlYWtlcnM9PTAsIGxvZygxKSwgbG9nKE51bWJlci5vZi5zcGVha2VycykpKQoKIyMgTWVyZ2UgZm9yIGFsbCB5ZWFycwpuZXcuZXh0PC1tZXJnZShuZXcuZXh0LCBlZC5nZHAsIGJ5Lng9IkNvdW50cnkuY29kZXMuYWxwaGEuMy5jb29yZCIsCiAgICAgICAgICAgICAgIGJ5LnkgPSAiQ291bnRyeS5Db2RlIiwgYWxsLng9VCkgJT4lIHNlbGVjdCAoIC0gbWF0Y2hlcygieWVhciIpICkKbmV3LmV4dDwtbmV3LmV4dCAlPiUgbXV0YXRlKEdEUC5wZXIuY2FwaXRhLmxvZyA9IGxvZyhgR0RQIHBlciBjYXBpdGEgKGN1cnJlbnQgVVMkKWApKQpuZXcuZXh0PC1uZXcuZXh0ICU+JSBtdXRhdGUoIGBGZW1hbGUuNzUrLmNvbXBsZXRlZC5zZWNvbmRhcnkubG9nYCA9IGxvZyhgQmFycm8tTGVlOiBQZXJjZW50YWdlIG9mIGZlbWFsZSBwb3B1bGF0aW9uIGFnZSA3NSsgd2l0aCBzZWNvbmRhcnkgc2Nob29saW5nLiBDb21wbGV0ZWQgU2Vjb25kYXJ5YCkpCm5ldy5leHQ8LW5ldy5leHQgJT4lIG11dGF0ZSggYEZlbWFsZS43NSsuY29tcGxldGVkLnNlY29uZGFyeWAgPSBgQmFycm8tTGVlOiBQZXJjZW50YWdlIG9mIGZlbWFsZSBwb3B1bGF0aW9uIGFnZSA3NSsgd2l0aCBzZWNvbmRhcnkgc2Nob29saW5nLiBDb21wbGV0ZWQgU2Vjb25kYXJ5YCkKbmV3LmV4dDwtbmV3LmV4dCAlPiUgc2VsZWN0KC1zdGFydHNfd2l0aCgiQmFycm8tTGVlOiIpKQpuZXcuZXh0PC1uZXcuZXh0ICU+JSBwbHlyOjpyZW5hbWUoYygiQ291bnRyeS5jb2Rlcy5hbHBoYS4zLmNvb3JkIiA9ICJDb3VudHJ5LkNvZGUiLCAiZWxldmF0aW9uIiA9ICJFbGV2YXRpb24iKSkKYGBgCgpgYGB7ciBwbG90UENBfQpwbG90UENBPC1mdW5jdGlvbihmLCBzLCBwY2EuYmFycm9sZWUsIGNvbG9yLCB0aXRsPVRSVUUpIHsKICBwbG90KHBjYS5iYXJyb2xlZSRzY29yZXNbLGZdLCBwY2EuYmFycm9sZWUkc2NvcmVzWyxzXSwgcGNoPTIxLAogICAgICAgeGxhYj1wYXN0ZShjKCJQQyIsZiwiKCIscHJvcHZhcltmXSwiJSkiKSwgY29sbGFwc2U9IiIpLAogICAgICAgeWxhYj1wYXN0ZShjKCJQQyIscywiKCIscHJvcHZhcltzXSwiJSkiKSwgY29sbGFwc2U9IiIpLAogICAgICAgY29sPXJnYigwLDAsMCwwKSwgYmc9Y29sb3JbdW5jbGFzcyhmYWN0b3IobmV3LmV4dCREZWdyZWUub2YuZW5kYW5nZXJtZW50LAogICAgICAgbGV2ZWxzPWMoIlZ1bG5lcmFibGUiLCAiRGVmaW5pdGVseSBlbmRhbmdlcmVkIiwgIlNldmVyZWx5IGVuZGFuZ2VyZWQiLCAKICAgICAgICAgICAgICAgICJDcml0aWNhbGx5IGVuZGFuZ2VyZWQiLCAiRXh0aW5jdCIpKSldKQogIGxlZ2VuZCgiYm90dG9tcmlnaHQiLCBkb2UubGV2ZWxzLCBjb2w9Y29sb3IsCiAgICAgICAgIGNleD0wLjcsCiAgICAgICAgIHBjaD1yZXAoMTksIGxlbmd0aChkb2UubGV2ZWxzKSkpCiAgaWYgKHRpdGwpCiAgICB0aXRsZShwYXN0ZSgiUENBIFBDIiwgZiwiIGFuZCBQQyIsIHMsIHNlcD0iIikpCn0KYGBg